<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" >

<title>Vue笔记（6） | 没想好的个人博客</title>

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

<!-- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"> -->
   <!-- Font Awesome CSS-->
   <link href="https://cdn.bootcss.com/font-awesome/5.13.0/css/all.css" rel="stylesheet">

   <link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/5.7.2/css/all.min.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

<link rel="shortcut icon" href="https://shixixiyue.gitee.io//favicon.ico?v=1709791195950">
<link rel="stylesheet" href="https://shixixiyue.gitee.io//styles/main.css">



<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<script src="https://jsd.onmicrosoft.cn/npm/vue/dist/vue.js"></script>


<style>
  .hljs-ln{
    padding-bottom: 1.2rem;
    margin: 0rem !important;
  }
  .hljs-ln td {
    border: none !important;
    padding: 2px 6px !important;
    line-height: 1.2rem;
    font-size: 1rem;
  }
  .hljs-ln tr td:first-child  {
    color: cadetblue;
    border-right: 1px solid !important;
  }
  .hljs-ln tr {
    border: none !important;
  }
</style>

    <meta name="description" content="
Vue + SignalR + .NET Core 2.2 通讯









1. 引用SignalR
2. 服务端注册使用
3. Vue端连接使用
4. 其他-invoke的响应








1. 引用SignalR
服务端略..." />
    <meta name="keywords" content="Vue笔记" />
  </head>
  <body>
    <div id="app" class="main">

      <div class="sidebar" :class="{ 'full-height': menuVisible }">
  <div class="top-container" data-aos="fade-right">
    <div class="top-header-container">
      <a class="site-title-container" href="https://shixixiyue.gitee.io/">
        <img src="https://shixixiyue.gitee.io//images/avatar.png?v=1709791195950" class="site-logo">
        <h1 class="site-title">没想好的个人博客</h1>
      </a>
      <div class="menu-btn" @click="menuVisible = !menuVisible">
        <div class="line"></div>
      </div>
    </div>
    <div>
      
        
          <a href="https://shixixiyue.gitee.io/" class="site-nav">
            首页
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/4gOKry8Qv/" class="site-nav">
            .Net Core
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/njETBpqXu/" class="site-nav">
            FineUICore
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/XyXyeLOBB" class="site-nav">
            读书笔记
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/TyVX6hfCJ" class="site-nav">
            Vue笔记
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/3Hz2sPtzO/" class="site-nav">
            产品
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/Db1wShB_E" class="site-nav">
            其他
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io/" class="site-nav">
            一一一一一一一一一
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//archives" class="site-nav">
            文章归档
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tags" class="site-nav">
            全部标签
          </a>
        
      
    </div>
  </div>
  <div class="bottom-container" data-aos="flip-up" data-aos-offset="0">
    <div class="social-container">
      
        
      
        
      
        
      
        
      
        
      
    </div>
    <div class="site-description">
      没事啥都说
    </div>
    <div class="site-footer">
      QQ：<a href="tencent://message/?uin=935732994&Site=''&Menu=yes">935732994<a/> <a href="http://beian.miit.gov.cn">京ICP备2024045283号<a/> | <a class="rss" href="https://shixixiyue.gitee.io//atom.xml" target="_blank">RSS</a>
    </div>
  </div>
</div>


      <div class="main-container">
        <div class="content-container" data-aos="fade-up">
          <div class="post-detail">
            <h2 class="post-title">Vue笔记（6）</h2>
            <div class="post-date">2020-12-04
            
                
                  <a href="https://shixixiyue.gitee.io/tag/TyVX6hfCJ/" class="tag">
                    Vue笔记
                  </a>
                
            </div>
            
            <div class="post-content" v-pre>
              <blockquote>
<p>Vue + SignalR + .NET Core 2.2 通讯</p>
</blockquote>
<!-- more -->
<p><ul class="markdownIt-TOC">
<li>
<ul>
<li>
<ul>
<li>
<ul>
<li><a href="#1-%E5%BC%95%E7%94%A8signalr">1. 引用SignalR</a></li>
<li><a href="#2-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B3%A8%E5%86%8C%E4%BD%BF%E7%94%A8">2. 服务端注册使用</a></li>
<li><a href="#3-vue%E7%AB%AF%E8%BF%9E%E6%8E%A5%E4%BD%BF%E7%94%A8">3. Vue端连接使用</a></li>
<li><a href="#4-%E5%85%B6%E4%BB%96-invoke%E7%9A%84%E5%93%8D%E5%BA%94">4. 其他-invoke的响应</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</p>
<h4 id="1-引用signalr">1. 引用SignalR</h4>
<p>服务端略</p>
<p>Vue 添加 依赖 @microsoft/signalr</p>
<pre><code>npm install @microsoft/signalr
</code></pre>
<h4 id="2-服务端注册使用">2. 服务端注册使用</h4>
<p>ConfigureServices 中加入 AddHttpContextAccessor 和 AddSignalR</p>
<pre><code>        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure&lt;CookiePolicyOptions&gt;(options =&gt;
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context =&gt; true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            //获取连接ID用的
            services.AddHttpContextAccessor();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            //添加SignalR
            services.AddSignalR();

            //MQ的注入
            services.AddSingleton&lt;IMyMQ, MyMQ&gt;();

        }
</code></pre>
<p>Configure中</p>
<pre><code>        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            /*这里引用的顺序如果不对会报跨域错误*/

            app.UseCors(builder =&gt; {
                //builder.WithOrigins(&quot;&quot;http://127.0.0.1:44325&quot;);//指定IP
                //builder.AllowAnyOrigin();//这个不好使
                builder.SetIsOriginAllowed(origin =&gt; true);
                builder.AllowAnyHeader();
                builder.AllowAnyMethod();
                builder.AllowCredentials();
            });

            app.UseWebSockets();

            //取个名Home 这个随便 前端跟他一样就行
            //ViewHub 是新建的类
            app.UseSignalR(routes =&gt;
            {
                routes.MapHub&lt;ViewHub&gt;(&quot;/Home&quot;);
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler(&quot;/Home/Error&quot;);
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();


            //app.UseSession();
            
            app.UseMvc(routes =&gt;
            {
                routes.MapRoute(
                    name: &quot;default&quot;,
                    template: &quot;{controller=Home}/{action=Index}/{id?}&quot;);
            });


        }
    }
</code></pre>
<p>ViewHub 类继承 Hub</p>
<pre><code>    public class ViewHub : Hub
    {
        /// &lt;summary&gt;
        /// websocket SignalR
        /// &lt;/summary&gt;
        private readonly IHubContext&lt;ViewHub&gt; _messageHub;
        /// &lt;summary&gt;
        /// MQ
        /// &lt;/summary&gt;
        private readonly IMyMQ _mymq;

        
        private readonly IHttpContextAccessor _accessor;

        //第一个是我的MQ注入，第二个是连接的注入
        public ViewHub(IMyMQ mymq, IHubContext&lt;ViewHub&gt; messageHub,IHttpContextAccessor accessor)
        {
            this._mymq = mymq;
            this._messageHub = messageHub;
            this._accessor = accessor;
            //发送消息
            messageHub.Clients.All.SendAsync(&quot;MQLOG&quot;, &quot;XXXX&quot;);
        }

        public override Task OnConnectedAsync()
        {
            //可以拿到当前连接的ID 作为标识
            string connId = Context.ConnectionId;

            //在连接时还可以传递其他信息
            //var token = _accessor.HttpContext.Request.Query[&quot;access_token&quot;];

            //给当前连接返回消息 .Clients可以发多个连接ID
            Clients.Client(connId).SendAsync(&quot;ConnectResponse&quot;, id+&quot;连接成功&quot;);
            
            return base.OnConnectedAsync();
        }

        //接收前端来的消息
        public async Task SendMessage(string theme, string data,string GUID)
        {
            JObject msg = new JObject();
            msg.Add(&quot;msg&quot;,&quot;发送成功&quot;);
            msg.Add(&quot;GUID&quot;, GUID);
            //也可以这样直接发送消息
            await Clients.All.SendAsync(&quot;MQSend&quot;, msg.ToString());
        }
    }
</code></pre>
<h4 id="3-vue端连接使用">3. Vue端连接使用</h4>
<p>建一个signalR.js</p>
<pre><code>import * as signalR from &quot;@microsoft/signalr&quot;;

//Url 注意/Home 跟服务端一致
const url = &quot;http://localhost:63437/Home&quot;;

const signal = new signalR.HubConnectionBuilder() //服务器地址
  .withUrl(url, { 
      //传递Token
      accessTokenFactory: () =&gt; &quot;00001&quot; 
    })
  .withAutomaticReconnect()//自动重连
  .build();
async function start() {
  try {
    await signal.start();
    console.log(&quot;connected&quot;);
  } catch (err) {
    console.log(err);
    //半自动重连
    //setTimeout(() =&gt; start(), 5000);
  }
}

//关闭
signal.onclose(async err =&gt; {
  //await start();
  console.log(err);
});

//将创建的signal赋值给Vue实例
export default {
  //install方法的第一个参数是 Vue 构造器，第二个参数是一个可选的选项对象。
  install: function(Vue) {
    Vue.prototype.signalr = signal;
  }
};

</code></pre>
<p>在main.js中引用</p>
<pre><code>import signalr from &quot;./utils/signalR&quot;;
Vue.use(signalr);
</code></pre>
<p>连接，这里写在了App.vue中</p>
<pre><code>  created() {
    //接收消息建议在start之前注册，至少注册一个
    //参照服务端 连接之后会有个ConnectResponse返回ID
    this.signalr.on(&quot;ConnectResponse&quot;, res =&gt; {
      //可以做相关业务逻辑
      console.log(res);
    });
    this.signalr.on(&quot;MQSend&quot;, res =&gt; {
        res = JSON.parse(res);
    });
  },
  mounted() {
    this.signalr.start().then(() =&gt; {
        console.log(&quot;连接&quot;);
    });
  },
  methods: {
    //向服务端发送消息
    async setMessage(theme, data) {
      return new Promise((resolve, reject) =&gt; {
          //对应服务端的SendMessage方法
          this.signalr
            .invoke(&quot;SendMessage&quot;, theme, JSON.stringify(data), guid)
            .catch(function(err) {
              console.error(err.toString())
              //reject(err.toString());
            });
          resolve('done')
      });
    });
  }
</code></pre>
<h4 id="4-其他-invoke的响应">4. 其他-invoke的响应</h4>
<p>到这就可以了，但是使用中 invoke 是不返回消息的，如果返回消息还要再下发，在 on 里接收，这是两个独立事件，业务页面我要先写个监听返回再写个发送方法，如果我能写成 await 形式就方便了，比如</p>
<pre><code>let res = await this.App.setMessage(&quot;XXX&quot;, {XXXX});
this.$message(res.msg);
</code></pre>
<p>这里要将App.vue中的setMessage重写，有返回结果后再执行Promise的resolve，</p>
<pre><code>async setMessage(theme, data) {
    //先取一个标识
    const guid = this.$newGUID();
    //存储当前的Promise
    let prom = {};
    //创建Promise 将GUID一并上传
    let p = new Promise((resolve, reject) =&gt; {
      this.signalr
        .invoke(&quot;SendMessage&quot;, theme, JSON.stringify(data), guid)
      //将resolve 缓存
      prom.resolve = resolve;
    });
    //将Promise缓存
    prom.p = p;
    //放到页面缓存
    this.MQsend[guid] = prom;
    //由于没有执行resolve 这个请求将一直挂起 直到执行resolve
    return p;
}
</code></pre>
<p>App.vue接收结果改为</p>
<pre><code>this.signalr.on(&quot;MQSend&quot;, res =&gt; {
    
    res = JSON.parse(res);

    /**
    *服务返回GUID
    *先找到缓存中GUID对应的Promise 
    *再执行resolve 执行后删除缓存 
    *这时Promise的状态改变 await结束
    */
    if (res.GUID &amp;&amp; this.MQsend[res.GUID]) {
      this.MQsend[res.GUID].resolve(res);
      delete this.MQsend[res.GUID];
    }
});
</code></pre>

            </div>
            
              <div class="tag-container">
                
                  <a href="https://shixixiyue.gitee.io/tag/TyVX6hfCJ/" class="tag">
                    Vue笔记
                  </a>
                
              </div>
            
            
              <div class="next-post">
                <div class="next">下一篇</div>
                <a href="https://shixixiyue.gitee.io/vue-bi-ji-5/">
                  <h3 class="post-title">
                    Vue笔记（5）
                  </h3>
                </a>
              </div>
            

            

          </div>

        </div>
      </div>
    </div>

    <script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script type="application/javascript">

AOS.init();

var app = new Vue({
  el: '#app',
  data: {
    menuVisible: false,
  },
})

</script>


  <script src="//jsd.onmicrosoft.cn/gh/highlightjs/cdn-release@11.5.1/build/highlight.min.js"></script>
  <script>
    hljs.initHighlightingOnLoad();
    //hljs.registerLanguage('mermaid', window.hljsDefineMermaid);
  </script>
  <script src="//jsd.onmicrosoft.cn/npm/highlightjs-line-numbers.js@2.8.0/dist/highlightjs-line-numbers.min.js"></script>
  <script>
    hljs.initLineNumbersOnLoad({
      singleLine: true
    });
  </script>
 <script src="https://jsd.onmicrosoft.cn/npm/mermaid/dist/mermaid.min.js"></script>
   <script>
    mermaid.initialize({
      startOnLoad: true,
      securityLevel: 'loose',
    });
  </script>





  </body>
</html>
